home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / ghostview-1.5 / SelFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  21.0 KB  |  754 lines

  1. /*
  2.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Software Research Associates not be used
  9.  * in advertising or publicity pertaining to distribution of the software
  10.  * without specific, written prior permission.  Software Research Associates
  11.  * makes no representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  16.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  18.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author: Erik M. van der Poel
  23.  *         Software Research Associates, Inc., Tokyo, Japan
  24.  *         erik@sra.co.jp
  25.  */
  26.  
  27. /*
  28.  * Author's address:
  29.  *
  30.  *     erik@sra.co.jp
  31.  *                                            OR
  32.  *     erik%sra.co.jp@uunet.uu.net
  33.  *                                            OR
  34.  *     erik%sra.co.jp@mcvax.uucp
  35.  *                                            OR
  36.  *     try junet instead of co.jp
  37.  *                                            OR
  38.  *     Erik M. van der Poel
  39.  *     Software Research Associates, Inc.
  40.  *     1-1-1 Hirakawa-cho, Chiyoda-ku
  41.  *     Tokyo 102 Japan. TEL +81-3-234-2692
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <errno.h>
  46. /* BSD 4.3 errno.h does not declare errno */
  47. extern int errno;
  48. extern int sys_nerr;
  49. extern char *sys_errlist[];
  50.  
  51. #include <sys/param.h>
  52. #include <X11/cursorfont.h>
  53. #include <X11/Intrinsic.h>
  54. #include <X11/StringDefs.h>
  55. #include <X11/Composite.h>
  56. #include <X11/Shell.h>
  57. #include <X11/Xaw/Form.h>
  58. #include <X11/Xaw/Command.h>
  59. #include <X11/Xaw/Scrollbar.h>
  60. #include <X11/Xaw/Label.h>
  61. #include <X11/Xaw/Cardinals.h>
  62.  
  63. #include "SFinternal.h"
  64.  
  65. #ifndef MAXPATHLEN
  66. #define MAXPATHLEN 1024
  67. #endif /* ndef MAXPATHLEN */
  68.  
  69. #if !defined(SVR4) && !defined(SYSV) && !defined(USG)
  70. extern char *getwd();
  71. #endif /* !defined(SVR4) && !defined(SYSV) && !defined(USG) */
  72.  
  73. int SFstatus = SEL_FILE_NULL;
  74.  
  75. char
  76.     SFstartDir[MAXPATHLEN],
  77.     SFcurrentPath[MAXPATHLEN],
  78.     SFcurrentDir[MAXPATHLEN];
  79.  
  80. Widget
  81.     selFile,
  82.     selFileCancel,
  83.     selFileField,
  84.     selFileForm,
  85.     selFileHScroll,
  86.     selFileHScrolls[3],
  87.     selFileLists[3],
  88.     selFileOK,
  89.     selFilePrompt,
  90.     selFileVScrolls[3];
  91.  
  92. Display *SFdisplay;
  93.  
  94. Pixel SFfore, SFback;
  95.  
  96. Atom    SFwmDeleteWindow;
  97.  
  98. XSegment SFsegs[2], SFcompletionSegs[2];
  99.  
  100. XawTextPosition SFtextPos;
  101.  
  102. int SFupperX, SFlowerY, SFupperY;
  103.  
  104. int SFtextX, SFtextYoffset;
  105.  
  106. int SFentryWidth, SFentryHeight;
  107.  
  108. int SFlineToTextH = 3;
  109.  
  110. int SFlineToTextV = 3;
  111.  
  112. int SFbesideText = 3;
  113.  
  114. int SFaboveAndBelowText = 2;
  115.  
  116. int SFcharsPerEntry = 15;
  117.  
  118. int SFlistSize = 10;
  119.  
  120. int SFworkProcAdded = 0;
  121.  
  122. XtAppContext SFapp;
  123.  
  124. int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
  125.  
  126. char SFtextBuffer[MAXPATHLEN];
  127.  
  128. XtIntervalId SFdirModTimerId;
  129.  
  130. int (*SFfunc)();
  131.  
  132. static char *oneLineTextEditTranslations = "\
  133.     <Key>Return:    redraw-display()\n\
  134.     Ctrl<Key>M:    redraw-display()\n\
  135. ";
  136.  
  137. /* ARGSUSED */
  138. static void
  139. SFexposeList(w, n, event, cont)
  140.     Widget        w;
  141.     XtPointer    n;
  142.         XEvent       *event;
  143.         Boolean         *cont;
  144. {
  145.     if ((event->type == NoExpose) || event->xexpose.count) {
  146.         return;
  147.     }
  148.  
  149.     SFdrawList(n, SF_DO_NOT_SCROLL);
  150. }
  151.  
  152. /* ARGSUSED */
  153. static void
  154. SFmodVerifyCallback(w, client_data, event, cont)
  155.     Widget            w;
  156.     XtPointer        client_data;
  157.         XEvent                    *event;
  158.         Boolean                 *cont;
  159. {
  160.     char    buf[2];
  161.  
  162.     if (
  163.         (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
  164.         ((*buf) == '\r')
  165.     ) {
  166.         SFstatus = SEL_FILE_OK;
  167.     } else {
  168.         SFstatus = SEL_FILE_TEXT;
  169.     }
  170. }
  171.  
  172. /* ARGSUSED */
  173. static void
  174. SFokCallback(w, cl, cd)
  175.     Widget    w;
  176.         XtPointer cl, cd;
  177. {
  178.     SFstatus = SEL_FILE_OK;
  179. }
  180.  
  181. static XtCallbackRec SFokSelect[] = {
  182.     { SFokCallback, (XtPointer) NULL },
  183.     { NULL, (XtPointer) NULL },
  184. };
  185.  
  186. /* ARGSUSED */
  187. static void
  188. SFcancelCallback(w, cl, cd)
  189.     Widget    w;
  190.         XtPointer cl, cd;
  191. {
  192.     SFstatus = SEL_FILE_CANCEL;
  193. }
  194.  
  195. static XtCallbackRec SFcancelSelect[] = {
  196.     { SFcancelCallback, (XtPointer) NULL },
  197.     { NULL, (XtPointer) NULL },
  198. };
  199.  
  200. /* ARGSUSED */
  201. static void
  202. SFdismissAction(w, event, params, num_params)
  203.     Widget    w;
  204.     XEvent *event;
  205.     String *params;
  206.     Cardinal *num_params;
  207. {
  208.     if (event->type == ClientMessage &&
  209.         event->xclient.data.l[0] != SFwmDeleteWindow) return;
  210.  
  211.     SFstatus = SEL_FILE_CANCEL;
  212. }
  213.  
  214. static char *wmDeleteWindowTranslation = "\
  215.     <Message>WM_PROTOCOLS:    SelFileDismiss()\n\
  216. ";
  217.  
  218. static XtActionsRec actions[] = {
  219.     {"SelFileDismiss",    SFdismissAction},
  220. };
  221.  
  222. static void
  223. SFcreateWidgets(toplevel, prompt, ok, cancel)
  224.     Widget    toplevel;
  225.     char    *prompt;
  226.     char    *ok;
  227.     char    *cancel;
  228. {
  229.     Cardinal    i, n;
  230.     int        listWidth, listHeight;
  231.     int        listSpacing = 10;
  232.     int        scrollThickness = 15;
  233.     int        hScrollX, hScrollY;
  234.     int        vScrollX, vScrollY;
  235.     Cursor
  236.             xtermCursor,
  237.             sbRightArrowCursor,
  238.             dotCursor;
  239.     Arg        arglist[20];
  240.  
  241.     i = 0;
  242.     XtSetArg(arglist[i], XtNtransientFor, toplevel);        i++;
  243.  
  244.     selFile = XtAppCreateShell("selFile", "SelFile",
  245.         transientShellWidgetClass, SFdisplay, arglist, i);
  246.  
  247.     /* Add WM_DELETE_WINDOW protocol */
  248.     XtAppAddActions(XtWidgetToApplicationContext(selFile),
  249.         actions, XtNumber(actions));
  250.     XtOverrideTranslations(selFile,
  251.         XtParseTranslationTable(wmDeleteWindowTranslation));
  252.  
  253.     i = 0;
  254.     XtSetArg(arglist[i], XtNdefaultDistance, 30);            i++;
  255.     selFileForm = XtCreateManagedWidget("selFileForm",
  256.         formWidgetClass, selFile, arglist, i);
  257.  
  258.     i = 0;
  259.     XtSetArg(arglist[i], XtNlabel, prompt);                i++;
  260.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  261.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  262.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  263.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  264.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  265.     XtSetArg(arglist[i], XtNborderWidth, 0);            i++;
  266.     selFilePrompt = XtCreateManagedWidget("selFilePrompt",
  267.         labelWidgetClass, selFileForm, arglist, i);
  268.  
  269.     i = 0;
  270.     XtSetArg(arglist[i], XtNforeground, &SFfore);            i++;
  271.     XtSetArg(arglist[i], XtNbackground, &SFback);            i++;
  272.     XtGetValues(selFilePrompt, arglist, i);
  273.  
  274.     SFinitFont();
  275.  
  276.     SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
  277.             SFbesideText;
  278.     SFentryHeight = SFaboveAndBelowText + SFcharHeight +
  279.             SFaboveAndBelowText;
  280.  
  281.     listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
  282.             scrollThickness;
  283.     listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  284.             SFlineToTextV + SFlistSize * SFentryHeight +
  285.             SFlineToTextV + 1 + scrollThickness;
  286.  
  287.     SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
  288.  
  289.     hScrollX = -1;
  290.     hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  291.             SFlineToTextV + SFlistSize * SFentryHeight +
  292.             SFlineToTextV;
  293.     SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
  294.  
  295.     vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
  296.     vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
  297.     SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
  298.             SFlineToTextV;
  299.  
  300.     SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
  301.     SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  302.             SFlineToTextV;
  303.     SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  304.             SFlineToTextV + SFlistSize * SFentryHeight - 1;
  305.  
  306.     SFtextX = SFlineToTextH + SFbesideText;
  307.     SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
  308.  
  309.     SFsegs[0].x1 = 0;
  310.     SFsegs[0].y1 = vScrollY;
  311.     SFsegs[0].x2 = vScrollX - 1;
  312.     SFsegs[0].y2 = vScrollY;
  313.     SFsegs[1].x1 = vScrollX;
  314.     SFsegs[1].y1 = 0;
  315.     SFsegs[1].x2 = vScrollX;
  316.     SFsegs[1].y2 = vScrollY - 1;
  317.  
  318.     SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
  319.     SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
  320.         SFlineToTextH + SFentryWidth - 1;
  321.  
  322.     i = 0;
  323.     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
  324.                                     i++;
  325.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  326.  
  327.     XtSetArg(arglist[i], XtNfromVert, selFilePrompt);        i++;
  328.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  329.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  330.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  331.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  332.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  333.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  334.     XtSetArg(arglist[i], XtNstring, SFtextBuffer);            i++;
  335.     XtSetArg(arglist[i], XtNlength, MAXPATHLEN);            i++;
  336.     XtSetArg(arglist[i], XtNeditType, XawtextEdit);            i++;
  337.     XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);            i++;
  338.     XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);        i++;
  339.     XtSetArg(arglist[i], XtNuseStringInPlace, True);        i++;
  340.     selFileField = XtCreateManagedWidget("selFileField",
  341.         asciiTextWidgetClass, selFileForm, arglist, i);
  342.  
  343.     XtOverrideTranslations(selFileField,
  344.         XtParseTranslationTable(oneLineTextEditTranslations));
  345.     XtSetKeyboardFocus(selFileForm, selFileField);
  346.  
  347.     i = 0;
  348.     XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);    i++;
  349.     XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);        i++;
  350.     XtSetArg(arglist[i], XtNheight, scrollThickness);        i++;
  351.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  352.     XtSetArg(arglist[i], XtNfromVert, selFileField);        i++;
  353.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  354.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  355.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  356.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  357.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  358.     selFileHScroll = XtCreateManagedWidget("selFileHScroll",
  359.         scrollbarWidgetClass, selFileForm, arglist, i);
  360.  
  361.     XtAddCallback(selFileHScroll, XtNjumpProc,
  362.         SFpathSliderMovedCallback, (XtPointer) NULL);
  363.     XtAddCallback(selFileHScroll, XtNscrollProc,
  364.         SFpathAreaSelectedCallback, (XtPointer) NULL);
  365.  
  366.     i = 0;
  367.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  368.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  369.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  370.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  371.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  372.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  373.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  374.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  375.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  376.     selFileLists[0] = XtCreateManagedWidget("selFileList1",
  377.         compositeWidgetClass, selFileForm, arglist, i);
  378.  
  379.     i = 0;
  380.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  381.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  382.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  383.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);        i++;
  384.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  385.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  386.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  387.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  388.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  389.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  390.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  391.     selFileLists[1] = XtCreateManagedWidget("selFileList2",
  392.         compositeWidgetClass, selFileForm, arglist, i);
  393.  
  394.     i = 0;
  395.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  396.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  397.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  398.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);        i++;
  399.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  400.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  401.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  402.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  403.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  404.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  405.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  406.     selFileLists[2] = XtCreateManagedWidget("selFileList3",
  407.         compositeWidgetClass, selFileForm, arglist, i);
  408.  
  409.     for (n = 0; n < 3; n++) {
  410.  
  411.         i = 0;
  412.         XtSetArg(arglist[i], XtNx, vScrollX);            i++;
  413.         XtSetArg(arglist[i], XtNy, vScrollY);            i++;
  414.         XtSetArg(arglist[i], XtNwidth, scrollThickness);    i++;
  415.         XtSetArg(arglist[i], XtNheight, SFvScrollHeight);    i++;
  416.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  417.         selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
  418.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  419.  
  420.         XtAddCallback(selFileVScrolls[n], XtNjumpProc,
  421.             SFvFloatSliderMovedCallback, (XtPointer) n);
  422.         XtAddCallback(selFileVScrolls[n], XtNscrollProc,
  423.             SFvAreaSelectedCallback, (XtPointer) n);
  424.  
  425.         i = 0;
  426.  
  427.         XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  428.                                     i++;
  429.         XtSetArg(arglist[i], XtNx, hScrollX);            i++;
  430.         XtSetArg(arglist[i], XtNy, hScrollY);            i++;
  431.         XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);        i++;
  432.         XtSetArg(arglist[i], XtNheight, scrollThickness);    i++;
  433.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  434.         selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
  435.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  436.  
  437.         XtAddCallback(selFileHScrolls[n], XtNjumpProc,
  438.             SFhSliderMovedCallback, (XtPointer) n);
  439.         XtAddCallback(selFileHScrolls[n], XtNscrollProc,
  440.             SFhAreaSelectedCallback, (XtPointer) n);
  441.     }
  442.  
  443.     i = 0;
  444.     XtSetArg(arglist[i], XtNlabel, ok);                i++;
  445.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  446.     XtSetArg(arglist[i], XtNcallback, SFokSelect);            i++;
  447.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  448.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  449.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  450.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  451.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  452.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  453.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  454.     selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
  455.         selFileForm, arglist, i);
  456.  
  457.     i = 0;
  458.     XtSetArg(arglist[i], XtNlabel, cancel);                i++;
  459.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  460.     XtSetArg(arglist[i], XtNcallback, SFcancelSelect);        i++;
  461.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  462.     XtSetArg(arglist[i], XtNfromHoriz, selFileOK);            i++;
  463.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  464.     XtSetArg(arglist[i], XtNhorizDistance, 30);            i++;
  465.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  466.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  467.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  468.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  469.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  470.     selFileCancel = XtCreateManagedWidget("selFileCancel",
  471.         commandWidgetClass, selFileForm, arglist, i);
  472.  
  473.     XtSetMappedWhenManaged(selFile, False);
  474.     XtRealizeWidget(selFile);
  475.  
  476.     /* Add WM_DELETE_WINDOW protocol */
  477.     SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
  478.     XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
  479.  
  480.     SFcreateGC();
  481.  
  482.     xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
  483.  
  484.     sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
  485.     dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
  486.  
  487.     XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
  488.     XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
  489.  
  490.     for (n = 0; n < 3; n++) {
  491.         XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
  492.             sbRightArrowCursor);
  493.     }
  494.     XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
  495.     XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
  496.  
  497.     for (n = 0; n < 3; n++) {
  498.         XtAddEventHandler(selFileLists[n], ExposureMask, True,
  499.             SFexposeList, (XtPointer) n);
  500.         XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
  501.             SFenterList, (XtPointer) n);
  502.         XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
  503.             SFleaveList, (XtPointer) n);
  504.         XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
  505.             SFmotionList, (XtPointer) n);
  506.         XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
  507.             SFbuttonPressList, (XtPointer) n);
  508.         XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
  509.             SFbuttonReleaseList, (XtPointer) n);
  510.     }
  511.  
  512.     XtAddEventHandler(selFileField, KeyPressMask, False,
  513.         SFmodVerifyCallback, (XtPointer) NULL);
  514.  
  515.     SFapp = XtWidgetToApplicationContext(selFile);
  516.  
  517. }
  518.  
  519. /* position widget under the cursor */
  520. void
  521. SFpositionWidget(w)
  522.     Widget w;
  523. {
  524.     Arg args[3];
  525.     Cardinal num_args;
  526.     Dimension width, height, b_width;
  527.     int x, y, max_x, max_y;
  528.     Window root, child;
  529.     int dummyx, dummyy;
  530.     unsigned int dummymask;
  531.     
  532.     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  533.           &dummyx, &dummyy, &dummymask);
  534.     num_args = 0;
  535.     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  536.     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  537.     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  538.     XtGetValues(w, args, num_args);
  539.  
  540.     width += 2 * b_width;
  541.     height += 2 * b_width;
  542.  
  543.     x -= ( (Position) width/2 );
  544.     if (x < 0) x = 0;
  545.     if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
  546.  
  547.     y -= ( (Position) height/2 );
  548.     if (y < 0) y = 0;
  549.     if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
  550.     
  551.     num_args = 0;
  552.     XtSetArg(args[num_args], XtNx, x); num_args++;
  553.     XtSetArg(args[num_args], XtNy, y); num_args++;
  554.     XtSetValues(w, args, num_args);
  555. }
  556.  
  557. FILE *
  558. SFopenFile(name, mode, prompt, failed)
  559.     char *name;
  560.     char *mode;
  561.     char *prompt;
  562.     char *failed;
  563. {
  564.     Arg args[1];
  565.     FILE *fp;
  566.  
  567.     SFchdir(SFstartDir);
  568.     if ((fp = fopen(name, mode)) == NULL) {
  569.     char *buf;
  570.     if (errno <= sys_nerr) {
  571.         buf = XtMalloc(strlen(failed) + strlen(sys_errlist[errno]) + 
  572.                strlen(prompt) + 2);
  573.         strcpy(buf, failed);
  574.         strcat(buf, sys_errlist[errno]);
  575.         strcat(buf, "\n");
  576.         strcat(buf, prompt);
  577.     } else {
  578.         buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
  579.         strcpy(buf, failed);
  580.         strcat(buf, "\n");
  581.         strcat(buf, prompt);
  582.     }
  583.     XtSetArg(args[0], XtNlabel, buf);
  584.     XtSetValues(selFilePrompt, args, ONE);
  585.     XtFree(buf);
  586.     return NULL;
  587.     }
  588.     return fp;
  589. }
  590.  
  591. SFtextChanged()
  592. {
  593.  
  594.     if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
  595.         (void) strcpy(SFcurrentPath, SFtextBuffer);
  596.  
  597.         SFtextPos = XawTextGetInsertionPoint(selFileField);
  598.     } else {
  599.         (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
  600.  
  601.         SFtextPos = XawTextGetInsertionPoint(selFileField) +
  602.             strlen(SFstartDir);
  603.     }
  604.  
  605.     if (!SFworkProcAdded) {
  606.         (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
  607.         SFworkProcAdded = 1;
  608.     }
  609.  
  610.     SFupdatePath();
  611. }
  612.  
  613. static char *
  614. SFgetText()
  615. {
  616.     return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
  617.         SFtextBuffer);
  618. }
  619.  
  620. static
  621. SFprepareToReturn()
  622. {
  623.     SFstatus = SEL_FILE_NULL;
  624.     XtRemoveGrab(selFile);
  625.     XtUnmapWidget(selFile);
  626.     XtRemoveTimeOut(SFdirModTimerId);
  627.     if (SFchdir(SFstartDir)) {
  628.         XtAppError(
  629.             SFapp,
  630.             "XsraSelFile: can't return to current directory"
  631.         );
  632.     }
  633. }
  634.  
  635. FILE *
  636. XsraSelFile(toplevel, prompt, ok, cancel, failed,
  637.         init_path, mode, show_entry, name_return)
  638.     Widget        toplevel;
  639.     char        *prompt;
  640.     char        *ok;
  641.     char        *cancel;
  642.     char        *failed;
  643.     char        *init_path;
  644.     char        *mode;
  645.     int        (*show_entry)();
  646.     char        **name_return;
  647. {
  648.     static int    firstTime = 1;
  649.     Cardinal    i;
  650.     Arg        arglist[20];
  651.     XEvent        event;
  652.     FILE        *fp;
  653.  
  654.     if (!prompt) {
  655.         prompt = "Pathname:";
  656.     }
  657.  
  658.     if (!ok) {
  659.         ok = "OK";
  660.     }
  661.  
  662.     if (!cancel) {
  663.         cancel = "Cancel";
  664.     }
  665.  
  666.     if (firstTime) {
  667.         firstTime = 0;
  668.         SFdisplay = XtDisplay(toplevel);
  669.         SFcreateWidgets(toplevel, prompt, ok, cancel);
  670.     } else {
  671.         i = 0;
  672.  
  673.         XtSetArg(arglist[i], XtNlabel, prompt);            i++;
  674.         XtSetValues(selFilePrompt, arglist, i);
  675.  
  676.         i = 0;
  677.         XtSetArg(arglist[i], XtNlabel, ok);            i++;
  678.         XtSetValues(selFileOK, arglist, i);
  679.  
  680.         i = 0;
  681.         XtSetArg(arglist[i], XtNlabel, cancel);            i++;
  682.         XtSetValues(selFileCancel, arglist, i);
  683.     }
  684.  
  685.     SFpositionWidget(selFile);
  686.     XtMapWidget(selFile);
  687.  
  688. #if defined(SVR4) || defined(SYSV) || defined(USG)
  689.     if (!getcwd(SFstartDir, MAXPATHLEN)) {
  690. #else /* defined(SVR4) || defined(SYSV) || defined(USG) */
  691.     if (!getwd(SFstartDir)) {
  692. #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */
  693.  
  694.         XtAppError(SFapp, "XsraSelFile: can't get current directory");
  695.     }
  696.     (void) strcat(SFstartDir, "/");
  697.     (void) strcpy(SFcurrentDir, SFstartDir);
  698.  
  699.     if (init_path) {
  700.         if (init_path[0] == '/') {
  701.             (void) strcpy(SFcurrentPath, init_path);
  702.             if (strncmp(
  703.                 SFcurrentPath,
  704.                 SFstartDir,
  705.                 strlen(SFstartDir)
  706.             )) {
  707.                 SFsetText(SFcurrentPath);
  708.             } else {
  709.                 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  710.             }
  711.         } else {
  712.             (void) strcat(strcpy(SFcurrentPath, SFstartDir),
  713.                 init_path);
  714.             SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  715.         }
  716.     } else {
  717.         (void) strcpy(SFcurrentPath, SFstartDir);
  718.     }
  719.  
  720.     SFfunc = show_entry;
  721.  
  722.     SFtextChanged();
  723.  
  724.     XtAddGrab(selFile, True, True);
  725.  
  726.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  727.         SFdirModTimer, (XtPointer) NULL);
  728.  
  729.     while (1) {
  730.         XtAppNextEvent(SFapp, &event);
  731.         XtDispatchEvent(&event);
  732.         switch (SFstatus) {
  733.         case SEL_FILE_TEXT:
  734.             SFstatus = SEL_FILE_NULL;
  735.             SFtextChanged();
  736.             break;
  737.         case SEL_FILE_OK:
  738.             *name_return = SFgetText();
  739.             if (fp = SFopenFile(*name_return, mode,
  740.                         prompt, failed)) {
  741.                 SFprepareToReturn();
  742.                 return fp;
  743.             }
  744.             SFstatus = SEL_FILE_NULL;
  745.             break;
  746.         case SEL_FILE_CANCEL:
  747.             SFprepareToReturn();
  748.             return NULL;
  749.         case SEL_FILE_NULL:
  750.             break;
  751.         }
  752.     }
  753. }
  754.